$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)) + '/lib')

require 'rubygems'
require 'test/unit'

require 'uranium/constants'
require 'uranium/dbwrapper'
require 'uranium/testrunner'
require 'uranium/utils'

at_exit{
	UraniumQuery.finalize_run(Uranium.run_id, Uranium.mode) if $run_id.to_i > 0
	Uranium.kill_selenium if $selenium_started
}

$selenium_port   = 4444
$default_locale  = 'en'
$default_browser = '*chrome'

class Uranium
    @@run_id          = nil
    @@case_ids        = nil
    @@suite_ids       = nil
    @@conf_path       = nil
    @@mode            = MODE_ALL
    @@path_to_tests   = File.expand_path(File.dirname(__FILE__)) + "/tests"
    
    def self.parse_args
        ARGV.each do |arg|
            hash, value = arg.split('=')
            
            case(hash)
                when '-r', '-run', 'runId'
                    @@run_id        = value
                when '-conf_path'
					@@conf_path = value
                when '-c', '-case', '-caseId', '-cases', '-caseIds'
                    @@mode          = MODE_CASES
                    @@case_ids      = value.split(',')
                when '-s', '-suite', '-suiteId', '-suites', '-suiteIds'
                    @@mode          = MODE_SUITES unless (@@mode == MODE_CASES || @@mode == MODE_NEW)
                    @@suite_ids     = value.strip
				when '-p', '-port'
					$selenium_port  = value.to_i
                when '--list-suites'
                    @@mode          = MODE_LIST_SUITES
                    @@run_id        = 0
                when '--all-fails'
                    @@mode          = MODE_ALL_FAILS
                when '--continue'
                    @@mode          = MODE_NOT_RUN
				when '--get-version'
					puts Callbacks.get_version
					exit!
                when '-m', 'mode'
                    case(value)
                        when MODE_ALL_FAILS, MODE_NOT_RUN:
                            @@mode = value
                        else
                            puts "mode #{value} is not a valid mode"
                            Uranium::display_usage
                    end
                else
					@@run_id = arg.strip
            end
        end
    
		$run_id = @@run_id
		$mode = @@mode
    
		if (@@run_id.to_i == 0)
			@@run_id = 'test';
			$run_id = 'test';
			puts "***Starting in test mode.  Results will not be posted to the database***\n\n\n" if @@mode != MODE_LIST_SUITES
		end
        
		$details = @@conf_path != nil ? RunDetails.init_with_json_file(@@conf_path) : RunDetails.init(@@run_id)
	end
    
    def self.display_usage
		usage = <<-TXT
Usage: ruby run.rb #runID [options]

options:
  -case             Specify single testcase to rerun
  -suite            Specify single suite to rerun
  --all-fails       Rerun all failed/cancelled testcases
  --continiue       Continue running automation run from where it was left off
TXT
    
		puts usage
		exit!
    end
    
    def self.main
		begin
			Uranium::parse_args
			Uranium::run(@@run_id, @@mode)
		rescue Exception => e
			Log.debug e.inspect
			Log.debug e.backtrace.inspect
		end
    end

    def self.list_suites
        require "enumerator" 
     
        l = Log.get_log_level
        Log.set_log_level(Log::NONE)
		TestRunner.load_test_scripts(@@path_to_tests)
        Log.set_log_level(l)
     
        suites = ObjectSpace.enum_for(:each_object, class << Test::Unit::TestCase; self; end).to_a
		suites.each_index do |i|
			suites[i] = suites[i].to_s
		end
        suites.delete('Test::Unit::TestCase')
    
        return suites.uniq.sort
    end

    def self.run(run_id, mode=MODE_ALL)
		if run_id == 'test' && mode==MODE_ALL
			Log.debug "Error: cannot run all under test mode.  Please specify a suite or testcase to run"
			exit!
		end
    
		if mode!=MODE_LIST_SUITES
			TestRunner.load_test_scripts(@@path_to_tests)
			suites = UraniumQuery.start_run(run_id, mode,{'case_ids' => @@case_ids, 'suite_ids' => @@suite_ids})
		end
=begin
      Uranium.start_selenium
      Browser.set_browser(RunDetails._BrowserType)
      Browser.set_locale(RunDetails.Locale)
    end
=end

		case mode
			when MODE_LIST_SUITES
				puts Uranium::list_suites.join(',')
				return
			when MODE_ALL, MODE_NOT_RUN
				suites.each do |suite|
					TestRunner.run_suite(suite, run_id)
				end
			when MODE_SUITES
				@@suite_ids.each do |s|
					TestRunner.run_suite(s, run_id, true)
				end
			when MODE_CASES
				Log.debug "Run individual cases: #{@@case_ids.join(',')}"
    
				@@case_ids.each do |c|
					c,s = c.split('|')
					TestRunner.run_test_case(c, s, run_id)
				end
			when MODE_ALL_FAILS
				cases = UraniumQuery.get_waiting_cases(run_id)
				Log.debug "Run individual cases: #{cases.join(',')}"
      
				cases.each do |row|
					TestRunner.run_test_case(row['name'], row['suiteName'], run_id)
				end
		end

		Callbacks.on_init
    end

	def self.wait_for_selenium
		Log.debug "Waiting for the Selenium Server to come up"
		begin
			wait_for_success(20) do
				response = Page.post("http://localhost:#{$selenium_port}/selenium-server/driver/?cmd=blah")
				assert(response.match(/500/))
			end
		rescue
			Log.debug "Shutting down.  Selenium failed to start after 20s"
			exit
		end
	end
    
    def self.start_selenium
		return
        Log.debug "\nStarting Selenium Server on port #{$selenium_port}"
    
		cmd = "java -jar \"#{BASE_PATH}/lib/selenium/selenium-server.jar\" -firefoxProfileTemplate \"#{PATH_TO_FIREFOX_PROFILE}\" -singleWindow -port #{$selenium_port}"
		spawn_process(cmd)
		$selenium_started = true
    
		self.wait_for_selenium
    end
    
    def self.kill_selenium
        Log.debug "\nKilling Selenium Server"
		Browser.kill_selenium
    end

	def self.run_id
		return @@run_id
	end
  
	def self.mode
		return @@mode
	end
end

Uranium.main
